<script setup>
import { onMounted, ref, computed, useSlots, watch,onActivated,onDeactivated } from 'vue'
import { JBoltApi } from '@/service/request'
// 标志变量：是否是首次加载
const isFirstLoad = ref(true);
const slots = useSlots()
const props = defineProps({
    url: String,
    clearable: {
        type: Boolean,
        default: true
    },
    labelField: {
        type: String,
        default: 'text'
    },
    valueField: {
        type: String,
        default: 'value'
    },
    valueToNumber: {
        type: Boolean,
        default: false
    },
    valueJoin: {
        type: [String, Boolean],
        default: ','
    },
    value: {
        type: [Array, String, Number, null],
        default: null
    },
    options: {
        type: Array,
        default: () => []
    },
    multiple: {
        type: Boolean,
        default: false
    }
})

const emit = defineEmits(['update:value'])

// 监听url变化，重新加载数据
watch([() => props.url, () => props.options], () => {
    loadOptions()
})

const value = computed(() => {
    if (!props.multiple) {
        //处理单选
        if (props.value && typeof props.value != 'number' && props.valueToNumber) {
            return Number(props.value)
        }
        return props.value
    }
    //处理多选
    if (!props.value) return []
    if (Array.isArray(props.value)) {
        return [...props.value]
    }
    if (typeof props.value == 'string') {
        if (props.valueJoin === false) {
            throw new Error(
                '检测到jb-select在多选模式下传入了一个字符串，valueJoin必须为有效的分割字符，否则组件无法解析'
            )
        }

        return props.value.split(props.valueJoin).map((v) => {
            if (props.valueToNumber) {
                return Number(v)
            }
            return v
        })
    }
    return props.value
})

function onValueChange(v) {
    if (!props.multiple) {
        emit('update:value', v)
        return
    }
    console.debug(v)
    //多选模式下
    emit(
        'update:value',
        Array.isArray(props.value) || props.valueJoin === false
            ? v
            : v.join(props.valueJoin)
    )
}

const loading = ref(false)
const dynamicOptions = ref([])

/**
 * 处理数据
 * @param options
 */
function processData(options = []) {
    dynamicOptions.value = options.map((item) => {
        if (props.valueToNumber) {
            item[props.valueField] = Number(item[props.valueField])
        }
        return item
    })
}

function loadOptions() {
    if (!props.url) {
        processData(props.options)
        return
    }

    loading.value = true

    JBoltApi.get(props.url, null, {
        ignoreMsg: true
    })
        .then(({ error, result }) => {
            if (error) {
                dynamicOptions.value = []
                return
            }
            if (result) {
                processData(result.data)
            }
        })
        .finally(() => {
            loading.value = false
        })
}

onMounted(() => {
  console.log('onMounted - 首次加载');
  if (isFirstLoad.value) {
    loadOptions(); // 首次加载数据

  }
})
onActivated(() => {

  if (!isFirstLoad.value) {
    console.log('onActivated - 缓存激活');
    loadOptions(); // 缓存激活时刷新数据（非首次）
  }
})
onDeactivated(() => {
   isFirstLoad.value = false; // 标记为非首次
})


defineExpose({
    refresh: loadOptions
})
</script>

<template>
    <n-select
        :loading="loading"
        :clearable="clearable"
        :options="dynamicOptions"
        :multiple="props.multiple"
        :fallback-option="false"
        :label-field="labelField"
        :value-field="valueField"
        :value="value"
        @update:value="onValueChange"
    >
        <template v-for="(_item, key) in slots" :key="key" #[key]="data">
            <slot :name="key" v-bind="data ?? {}" />
        </template>
    </n-select>
</template>

<style scoped></style>
